// See LICENSE for license details.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include "hbird_sdk_soc.h"

#include "insn.h"
#include "startup.h"

#include "lcd_driver.h"
#include "system_veri.h"

unsigned int mrt_work=0, workmode=0;
uint64_t delta = SOC_TIMER_FREQ;

void rv_print_welcome(){
	srand(__get_rv_cycle()  | __get_rv_instret() | __RV_CSR_READ(CSR_MCYCLE));
	uint32_t rval = rand();
	rv_csr_t misa = __RV_CSR_READ(CSR_MISA);
	printf("MISA: 0x%lx\r\n", misa);
	print_misa();
	return ;
};

void mtimer_irq_handler(void)
{
	if(mrt_work & mrt_finish_flag){
		mrt_finish_flag = 0;
		printf("################################################\n");
		printf("u42a     = ");print_fixed_point(global_u42a, 32, 27, 0, 5);printf("\n");
		printf("sigma_dp = ");print_fixed_point(global_sigma, 32, 23, 0, 5);printf("\n");
		if(workmode){
			printf("gamma    = ");print_fixed_point(global_gamma, 32, 20, 0, 5);printf("\n");
			printf("psy      = ");print_fixed_point(global_psy, 32, 27, 1, 5);printf("\n");
			printf("----------------------------------------------- \n");
			printf("MRT RESULT: ");
			switch(mrt_type){
			case 0  : lcd_print(10,"No Input  ",1,6); printf("No input.\n"); break;
			case 1  : lcd_print(10,"ASK       ",1,6); printf("ASK.\n"); break;
			case 2  : lcd_print(10,"AM        ",1,6); printf("AM.\n"); break;
			case 4  : lcd_print(10,"USB       ",1,6); printf("USB.\n"); break;
			case 5  : lcd_print(10,"LSB       ",1,6); printf("LSB.\n"); break;
			case 8  : lcd_print(10,"QAM       ",1,6); printf("QAM.\n"); break;
			case 10 : lcd_print(10,"FM/FSK/PSK",1,6); printf("FM/FSK/PSK.\n"); break;
			default : lcd_print(10,"ERROR     ",1,6); printf("Error.\n"); break;
			}
		}
		else{
			printf("----------------------------------------------- \n");
			printf("MRT RESULT: ");
			switch(mrt_type){
			case 0  : lcd_print(10,"No Input  ",1,6); printf("No input.\n"); break;
			case 1  : lcd_print(10,"ASK       ",1,6); printf("ASK.\n"); break;
			case 2  : lcd_print(10,"AM        ",1,6); printf("AM.\n"); break;
			case 12 : lcd_print(10,"OTHER     ",1,6); printf("Other(FM/USB/LSB/QAM/FSK/PSK).\n"); break;
			default : lcd_print(10,"ERROR     ",1,6); printf("Error.\n"); break;
			}
		}
	}
    uint64_t now = SysTimer_GetLoadValue();
    SysTimer_SetCompareValue(now + delta);
}

void setup_timer()
{
    printf("init timer and start\n\r");
    uint64_t now = SysTimer_GetLoadValue();
    uint64_t then = now + delta;
    SysTimer_SetCompareValue(then);
}

int main(void)
{
    ///////////////////////////////////////////////////
    ///
    ///   system start up
    ///
    ///////////////////////////////////////////////////

    // to tell risc-v boot success.
	rv_print_welcome();

    // ask if need download program by uart
    uart_programming_entry();

    // module initialize
    gpio_init();
    lcd_init();
    lcd_print(16,"MRT CORE INSIDE!",0,0);
    lcd_print(16,"Find:           ",1,0);

    Core_Register_IRQ(SysTimer_IRQn, mtimer_irq_handler); /* register system timer interrupt */

    adc_init();
    mrt_intr_init();
    __enable_irq();
    setup_timer();
    ///////////////////////////////////////////////////
    ///
    ///   main function
    ///
    ///////////////////////////////////////////////////

    adc_select_type_and_start(0);

    printf("\n");

	printf("system ready for work:\r\n");
	printf("--------------------------------------------------------\r\n");
    while(1){
    	config();
		if(mrt_cfg_on != mrt_work){
			mrt_work = mrt_cfg_on;
			printf("mrt on/off: %d\n",mrt_work);
			mrt_start();
		}
		if(mrt_cfg_wm != workmode){
			workmode = mrt_cfg_wm;
			printf("mrt work mode: %d\n",workmode);
			if(workmode){
				custom_mrt_rdstat(0x80000020);
			}
			else{
				custom_mrt_rdstat(0x80000000);
			}
		}
		switch(mrt_cfg_ur){
			case 0:  delta = SOC_TIMER_FREQ<<1;break;
			case 1:  delta = SOC_TIMER_FREQ;   break;
			case 2:  delta = SOC_TIMER_FREQ>>1;break;
			case 3:  delta = SOC_TIMER_FREQ>>2;break;
			default: delta = SOC_TIMER_FREQ;   break;
		}
    }
    return 0;
}

